package com.kaibes.web.guard;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.kaibes.core.base.util.ListUtils;
import com.kaibes.core.base.util.StringUtils;
import com.kaibes.web.filter.BeforeFilterInternal;

@Component
public class BeforeFilterInternal4Guard implements BeforeFilterInternal {

    @Autowired
    private GuardProperties guardProperties;

    private static String getIpAddr(HttpServletRequest request) {
        if (request == null) {
            return "unknown";
        }
        String ip = request.getRemoteAddr();
        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
    }
    
    @Override
    public boolean beforeFilterInternal(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        if (guardProperties.isClosed()) {
            return false;
        }
        String clientIp = getIpAddr(request);
        if (clientIp.equals("127.0.0.1")) {
            return false;
        }
        List<RequestLimit> limits = guardProperties.getLimits();
        if (ListUtils.isEmpty(limits)) {
            return false;
        }
        List<RequestLimit> allows = new ArrayList<>();
        List<RequestLimit> refuses = new ArrayList<>();
        for (RequestLimit requestLimit : limits) {
            if (StringUtils.isBlankOrMatchers(requestLimit.getUri(), request.getRequestURI()) &&
                    StringUtils.isBlankOr(requestLimit.getMethod(), request.getMethod())) {
                if (requestLimit.isAllowed()) {
                    allows.add(requestLimit);
                } else {
                    refuses.add(requestLimit);
                }
            }
        }
        if (allows.isEmpty()) {
            if (refuses.isEmpty()) {
                return false;
            } else {
                for (RequestLimit requestLimit : refuses) {
                    if (check(requestLimit.getIps(), clientIp)) {
                        response.sendError(HttpServletResponse.SC_FORBIDDEN);
                        return true;
                    }
                }
                return false;
            }
        } else {
            for (RequestLimit requestLimit : allows) {
                if (check(requestLimit.getIps(), clientIp)) {
                    return false;
                }
            }
            response.sendError(HttpServletResponse.SC_FORBIDDEN);
            return true;
        }
    }
    
    private boolean check(List<String> ips, String clientIp) {
        for (String ip : ips) {
            if (ip.endsWith("0/24")) {
                ip = ip.substring(0, ip.lastIndexOf("."));
                if (clientIp.startsWith(ip)) {
                    return true;
                }
            } else {
                if (clientIp.equals(ip)) {
                    return true;
                }
            }
        }
        return false;
    }
}
